﻿using AgCIM.Tools.SpatialEncoding.Beidou;
using OfficeOpenXml;
using System.Data;
using System.Diagnostics;
using System.Text;
using Coordinate = AgCIM.Tools.SpatialEncoding.Beidou.Coordinate;

namespace StandardManager.EntityCode
{
    public partial class EntityDataForm : Form
    {
        private TreeView m_tree;
        private string[] m_selectedFields;
        private string m_classEncoding = string.Empty;
        private string m_locationEncodingField = string.Empty;
        private string m_locationField = string.Empty;
        private bool m_isSave = false;

        public EntityDataForm(string filePath, TreeView treeView1)
        {
            InitializeComponent();
            DataTable dt = ReadExcelFile(filePath);
            this.dataGridView1.DataSource = dt;
            m_tree = treeView1;
        }

        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (m_isSave) return;
            var result = MessageBox.Show("关闭窗口当前数据无法保存，是否关闭？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (result == DialogResult.No)
            {
                e.Cancel = true;
            }
        }

        private DataTable ReadExcelFile(string filePath)
        {
            using (var package = new OfficeOpenXml.ExcelPackage(new FileInfo(filePath)))
            {
                DataTable dt = new DataTable();
                if (package.Workbook.Worksheets.Count == 0)
                {
                    MessageBox.Show("当前excel文件中没有可用工作表");
                    return dt;
                }
                ExcelWorksheet worksheet = package.Workbook.Worksheets.First();

                // 读取表头
                foreach (var firstRowCell in worksheet.Cells[1, 1, 1, worksheet.Dimension.End.Column])
                {
                    dt.Columns.Add(firstRowCell.Text);
                }

                // 读取数据行
                for (int rowNum = 2; rowNum <= worksheet.Dimension.End.Row; rowNum++)
                {
                    DataRow dataRow = dt.NewRow();
                    for (int colNum = 1; colNum <= worksheet.Dimension.End.Column; colNum++)
                    {
                        // 获取单元格的值
                        var cellValue = worksheet.Cells[rowNum, colNum].Value;
                        dataRow[colNum - 1] = cellValue ?? DBNull.Value; // 使用 DBNull.Value 处理空单元格
                    }
                    dt.Rows.Add(dataRow);
                }

                return dt;
            }
        }

        private void 类型码字段配置ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataTable dt = dataGridView1.DataSource as DataTable;
            if (dt == null)
            {
                MessageBox.Show("没有数据表可以操作");
                return;
            }

            using (var fieldSelector = new FieldSelectorForm(dt, m_selectedFields, m_classEncoding))
            {
                if (fieldSelector.ShowDialog() == DialogResult.OK)
                {
                    m_selectedFields = fieldSelector.SelectedFields;
                    m_classEncoding = fieldSelector.CodeFieldName;
                    AddMergedField(m_selectedFields, dt, fieldSelector.CodeFieldName);
                }
            }
        }

        private void AddMergedField(string[] selectedFields, DataTable dt, string mergeFieldName)
        {
            if (selectedFields.Length == 0) { return; }
            // 新增类型码字段
            if (!dt.Columns.Contains(mergeFieldName))
            {
                dt.Columns.Add(mergeFieldName, typeof(string));
            }

            foreach (DataRow dr in dt.Rows)
            {
                string mergedValue = GetClassEncoding(dr, selectedFields);
                dr[mergeFieldName] = mergedValue;
            }
            dataGridView1.Refresh();
        }

        /// <summary>
        /// 生成类型码
        /// </summary>
        /// <param name="dr"></param>
        /// <param name="selectedFields"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private string GetClassEncoding(DataRow dr, string[] selectedFields)
        {
            string code = string.Empty;
            //GetClassEncoding(selectedFields, 0, dr, m_tree.Nodes, ref code);

            StringBuilder codeBuilder = new StringBuilder();
            List<TreeNode> currentNodes = new List<TreeNode>(m_tree.Nodes.Cast<TreeNode>());

            for (int i = 0; i < selectedFields.Length; i++)
            {
                string fieldName = selectedFields[i];
                string nodeName = dr[fieldName].ToString();

                List<TreeNode> nextNodes = new List<TreeNode>();
                if (currentNodes.Count <= 0 && i == selectedFields.Length - 1)
                {
                    codeBuilder.Append("000");
                    break;
                }
                if (string.IsNullOrEmpty(nodeName))
                {
                    break;
                }

                foreach (TreeNode node in currentNodes)
                {
                    var entityCode = node.Tag as EntityCode;
                    if (entityCode?.Name == nodeName)
                    {
                        codeBuilder.Append(entityCode.CodeValue);
                        nextNodes.AddRange(node.Nodes.Cast<TreeNode>());
                        break;
                    }
                }

                currentNodes = nextNodes;
            }

            code = codeBuilder.ToString();

            return code;
        }

        private bool GetClassEncoding(string[] selectedFields, int index, DataRow dr, TreeNodeCollection nodes, ref string code)
        {
            string filedName = selectedFields[index];
            string nodeName = dr[filedName].ToString();

            bool isMatch = false;
            foreach (TreeNode node in nodes)
            {
                var entityCode = node.Tag as EntityCode;
                if (entityCode.Name != nodeName)
                {
                    continue;
                }
                code += entityCode.CodeValue;
                if (index == selectedFields.Length - 1)
                {
                    return true;
                }
                isMatch = GetClassEncoding(selectedFields, ++index, dr, node.Nodes, ref code);
                break;
            }

            return isMatch;
        }

        private void 位置码ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataTable dt = dataGridView1.DataSource as DataTable;
            if (dt == null)
            {
                MessageBox.Show("没有数据表可以操作");
                return;
            }

            using (var fieldSelector = new LocationCodeForm(dt, m_locationEncodingField, m_locationField))
            {
                if (fieldSelector.ShowDialog() == DialogResult.OK)
                {
                    m_locationEncodingField = fieldSelector.CodeFieldName;
                    m_locationField = fieldSelector.LocationFieldName;
                    AddLocationField(m_locationEncodingField, m_locationField, dt);
                }
            }
        }

        private void AddLocationField(string saveField, string locationField, DataTable dt)
        {
            // 新增类型码字段
            if (!dt.Columns.Contains(saveField))
            {
                dt.Columns.Add(saveField, typeof(string));
            }

            foreach (DataRow dr in dt.Rows)
            {
                string locationCode = GetLocationEncoding(dr[locationField].ToString());
                dr[saveField] = locationCode;
            }
            dataGridView1.Refresh();
        }

        /// <summary>
        /// 获取当前位置北斗网格码，按照徐州标准网格精度为8级，且剔除前4位
        /// </summary>
        /// <param name="location"></param>
        /// <returns></returns>
        private string GetLocationEncoding(string location)
        {
            string code = string.Empty;
            if (string.IsNullOrEmpty(location))
            {
                return code;
            }

            List<Coordinate> coordinates = ExtractCoordinates(location);
            (Coordinate, Coordinate) bounds = GetCoordinateBounds(coordinates);
            var beidouCode = BeidouEncoder.Encode(bounds.Item1, bounds.Item2, 8);
            code = string.Join("", beidouCode.LocationCode);

            code = code.Length > 4 ? code.Substring(4) : "";

            return code;
        }

        private (Coordinate, Coordinate) GetCoordinateBounds(List<Coordinate> coordinates)
        {
            double minLon = double.MaxValue;
            double maxLon = double.MinValue;
            double minLat = double.MaxValue;
            double maxLat = double.MinValue;
            double minAlt = double.MaxValue;
            double maxAlt = double.MinValue;

            bool hasAltitude = false;
            foreach (Coordinate coord in coordinates)
            {
                if (coord.Lng < minLon) minLon = coord.Lng;
                if (coord.Lng > maxLon) maxLon = coord.Lng;
                if (coord.Lat < minLat) minLat = coord.Lat;
                if (coord.Lat > maxLat) maxLat = coord.Lat;
                if (coord.Alt.HasValue)
                {
                    hasAltitude = true;
                    if (coord.Alt < minAlt) minAlt = coord.Alt.Value;
                    if (coord.Alt > maxAlt) maxAlt = coord.Alt.Value;
                }
            }

            if (hasAltitude)
            {
                return (new Coordinate(minLon, minLat, minAlt), new Coordinate(maxLon, maxLat, maxAlt));
            }
            else
            {
                return (new Coordinate(minLon, minLat), new Coordinate(maxLon, maxLat));
            }
        }

        private List<Coordinate> ExtractCoordinates(string geometry)
        {
            List<Coordinate> coordinates = new List<Coordinate>();

            // 查找括号内容
            int startIdx = geometry.IndexOf('(');
            int endIdx = geometry.IndexOf(')');

            if (startIdx != -1 && endIdx != -1 && endIdx > startIdx)
            {
                string content = geometry.Substring(startIdx + 1, endIdx - startIdx - 1).Trim();

                // 按逗号分割
                var points = content.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

                foreach (var point in points)
                {
                    double longitude;
                    double latitude;
                    double altitude;
                    // 按空格分割
                    var coords = point.Trim().Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                    if (coords.Length == 2 &&
                        double.TryParse(coords[0], out longitude) &&
                        double.TryParse(coords[1], out latitude))
                    {
                        coordinates.Add(new Coordinate(longitude, latitude));
                    }
                    else if (coords.Length == 3 &&
                        double.TryParse(coords[0], out longitude) &&
                        double.TryParse(coords[1], out latitude) &&
                        double.TryParse(coords[2], out altitude))
                    {
                        coordinates.Add(new Coordinate(longitude, latitude, altitude));
                    }
                }
            }

            return coordinates;
        }

        private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            DataTable dt = dataGridView1.DataSource as DataTable;
            if (dt == null || dt.Rows.Count == 0)
            {
                MessageBox.Show("没有数据可以导出");
                return;
            }

            string localFilePath = "";
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "Excel表格（*.xlsx）|*.xlsx";
            sfd.RestoreDirectory = true;

            try
            {
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    localFilePath = sfd.FileName.ToString(); //获得文件路径 
                    ExportDatableToExcel(dt, localFilePath);
                    MessageBox.Show("导出成功");
                    m_isSave = true;
                    Process.Start("explorer.exe", localFilePath);
                }
            }
            catch (Exception error)
            {
                MessageBox.Show($"导出失败：{error}");
            }
        }

        private void ExportDatableToExcel(DataTable dataTable, string filePath)
        {
            using (ExcelPackage package = new ExcelPackage(new FileInfo(filePath)))
            {
                ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Sheet1");

                // 写入表头
                for (int i = 0; i < dataTable.Columns.Count; i++)
                {
                    worksheet.Cells[1, i + 1].Value = dataTable.Columns[i].ColumnName;
                }

                // 写入数据
                for (int i = 0; i < dataTable.Rows.Count; i++)
                {
                    for (int j = 0; j < dataTable.Columns.Count; j++)
                    {
                        worksheet.Cells[i + 2, j + 1].Value = dataTable.Rows[i][j];
                    }
                }

                package.Save();
            }
        }
    }
}
